#include "dht11.h"
#include "delay.h"

//发送开始信号和等待响应
u8 dht11_Start(void)
{
	u8 retry=0;
	DHT_OUT(); 						//设置为输出
	DHT11_DQ_OUT=0; 				//拉低DQ
	delay_ms(18);    				//拉低至少18ms
	DHT11_DQ_OUT=1; 				//DQ=1
	delay_us(30);     				//主机拉高20~40us

	DHT_IN();      					//设置为输入
	while (DHT11_DQ_IN&&retry<100)	//DHT11会拉低40~80us
	{
		retry++;					//计时
		delay_us(1);
	};
	if(retry>=100)return 1;			//超时返回1
	else retry=0;					//时间清零
	while (!DHT11_DQ_IN&&retry<100)	//DHT11拉低后会再次拉高40~80us
	{
		retry++;					//计时
		delay_us(1);
	};
	if(retry>=100)return 1;			//超时返回1
	return 0;
}

//从DHT11读取一个位
//返回值：1/0
u8 dht11ReadBit(void)
{
 	u8 retry=0;
	while(DHT11_DQ_IN&&retry<100)	//等待变为低电平
	{
		retry++;					//计时
		delay_us(1);
	}
	retry=0;						//时间清零
	while(!DHT11_DQ_IN&&retry<100)	//等待变高电平
	{
		retry++;					//计时
		delay_us(1);
	}
	delay_us(40);					//等待40us
	if(DHT11_DQ_IN)return 1;		//40us后读到的还是1,表明读到的是高电平
	else return 0;					//反之
}

//从DHT11读取一个字节
//返回值：读到的数据
u8 dht11ReadByte(void)
{
	u8 i,dat;
	dat=0;
	for (i=0;i<8;i++)
	{
		//一位一位的读，先读到的为高位
   		dat<<=1;
	    dat|=dht11ReadBit();
    }
    return dat;
}

//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值：0,正常;1,读取失败
u8 dht11Read(float *temp,float *humi)
{
 	u8 buf[5];
	u8 i;
	if(dht11_Start() == 0)
	{
		for(i=0;i<5;i++)			//读取40位数据
		{
			buf[i]=dht11ReadByte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=buf[0] + (float)buf[1]/(1<<7);			//获得湿度的整数值
			*temp=buf[2] + (float)buf[3]/(1<<7);			//获得温度的整数值
		}
		else return 1;				//异常状况
	}else return 1;					//异常状况
	return 0;
}
